#pragma once

#include<net/if.h>
#include<net/if_arp.h>
#include<netinet/in.h>
#include<sys/stat.h>
#include<sys/ipc.h>
#include<fcntl.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<sys/ioctl.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<pthread.h>
#include<iostream>
#include <sys/msg.h>
#include"ClientManager.h"
using namespace std;


#define MAX_BUFFER_SIZE 10240*8
#define LOCAL_IP "127.0.0.1"
#define ETH_NAME		"eth0"
#define WLAN_NAME     "wlan0"

static int rtspSock;

#define PROJ_ID     32
#define PATH_NAME   "/tmp"
#define SERVER_QMSG 0
#define CLIENT_QMSG 1

enum _CamState{
    CAM_STATE_PENDDING = 0,
    CAM_STATE_PLAYING = 1,
    CAM_STATE_STOP = 9,
    CAM_STATE_QUIT = 10
};


//system message queue
typedef struct StruQueueMsgbuf {
    long ltype;
    int iCommand;
    int iMarkTcp;
    char strAddr[20];
    int iPort;
    char strSession[20];
} QueueMsgbuf, *qQueueMsgbuf;

#define QMSG_SIZE    (sizeof(QueueMsgbuf)-sizeof(long))

class CRtpClient {

public:
    CRtpClient(void);
    CRtpClient(char* ip, unsigned int rtspPort, char* mode, char* url, char* rootPath, long lType);
public:
    ~CRtpClient(void);

public:
    void Run();
    void InitClient();
    const char* getServerIP() {
        return mServerIP.c_str();
    }
public:
    void ShowMenu();
    void YourChoose();
    char* GetLocalIP(char* name);
    static bool SetNonBlocking(int& Sock);

    void CreateRecvThread();
    static void* MediaThreadRtsp(void* paramPtr);
    static void* MediaThreadTcp(void* paramPtr);
    static void* MediaThreadUdp(void* paramPtr);

    void CreateMsgThread();
    static void* MsgQueryThread(void* paramPtr);

    void InitRtspSocket();
    void InitTcpSocket();
    void InitUdpSocket();

public:

    pthread_t rtspID;
    pthread_t tcpID;
    pthread_t udpID;

    pthread_t msgID;

    inline char* getPlay() {
        char buf[1024];
        sprintf(buf, "PLAY %s RTSP/1.0\r\n"
            "CSeq: %d\r\n"
            "Content-Length: 0\r\n"
            "Range: npt=0-\r\n"
            "Scale: 1\r\n"
            "Session: %s\r\n"
            "\r\n", mUrl.c_str(), mCseq++, mSession.c_str());

        return buf;
    }

    inline char* getSetup() {
        if (mUseTcp) {
            return getTcpSetup();
        } else {
            return getUdpSetup();
        }
    }

    inline char* getUdpSetup() {
        char buf[1024];

        sprintf(buf, "SETUP %s RTSP/1.0\r\n"
            "CSeq: %d\r\n"
            "Content-Length: 0\r\n"
            "Transport: RTP/AVP/UDP;unicast;client_port=%d-%d;mod=play\r\n"
            "\r\n", mUrl.c_str(), mCseq++, getRtpPort(), getRtpPort() + 1);

        return buf;
    }
    inline char* getTcpSetup() {
        char buf[1024];

        sprintf(buf, "SETUP %s RTSP/1.0\r\n"
            "CSeq: %d\r\n"
            "Content-Length: 0\r\n"
            "Transport: RTP/AVP/TCP;TCP;client_port=%d-%d;mod=play\r\n"
            "\r\n", mUrl.c_str(), mCseq++, getRtpPort(), getRtpPort() + 1);

        return buf;
    }
    inline char* getOptions() {
        char buf[1024];

        sprintf(buf, "OPTIONS %s RTSP/1.0\r\n"
            "CSeq: %d\r\n"
            "\r\n", mUrl.c_str(), mCseq++);
        return buf;
    }
    inline char* getDescribe() {
        char buf[1024];

        sprintf(buf, "DESCRIBE %s RTSP/1.0\r\n"
            "CSeq: %d\r\n"
            "Accept: application/sdp,application/rtsl,application/mheg\r\n"
            "Content-Length: 0\r\n"
            "\r\n", mUrl.c_str(), mCseq++);

        return buf;
    }
    inline char* getTearDown() {
        char buf[1024];
        sprintf(buf, "TEARDOWN %s RTSP/1.0\r\n"
            "CSeq: %d\r\n"
            "Session: %s\r\n"
            "\r\n", mUrl.c_str(), mCseq++, mSession.c_str());
        return buf;
    }
    //TODO
    inline int getRtpPort() {
        mRtpPort = 2000;
        return mRtpPort;
    }

    char* Send(char* str) {
        char rtspBuf[10240];
        if (send(rtspSock, str, strlen(str), 0) < 0) {
            perror("send");
            exit(1);
        }
        //Recv Response
        int len = recv(rtspSock, rtspBuf, sizeof(rtspBuf) - 1, 0);
        if (len < 0) {
            perror("recv");
            exit(1);
        }
        rtspBuf[len] = '\0';
        cout << "Received Response:\n" << rtspBuf << endl;
        return rtspBuf;
    }

    void setSession(char* str) {
        //从Setup回复中，读取Session ID
        std::string _tempstr = str;
        std::size_t pos = std::string::npos;
        pos = _tempstr.find("Session:");
        if (pos == std::string::npos) {
            perror("no Session ID");
            exit(1);
        }
        string strSession;
        strSession.append(_tempstr.substr(pos + 9));
        pos = strSession.find("\r\n");
        mSession.append(strSession.substr(0, pos));
        //		int nSession = atoi(strSession.c_str());
        //		char _session[32];
        //		sprintf(_session,"%s",nSession);
        //		mSession.append(_session);
    }

protected:
    key_t mMsgkey;
    string mServerIP, mLocalIP, mUrl, mRootPath, mSession;
    int mCseq, mRtspPort, mRtpPort;
    int mUseTcp;
    int mIsRtpRunning, mIsMsgQueryRunning;
    int mCamState;
};

extern CClientManager *gClientManager;
extern CRtpClient* gRtpClient;

